package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.conditions.AbstractChainWrapper;
import com.heima.api.IArticleClient;
import com.heima.api.UserClient;
import com.heima.comment.mapper.ApCommentsConfigMapper;
import com.heima.common.exception.CustomException;
import com.heima.model.article.dtos.ApArticleDto;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.comment.dtos.ApCommentDto;
import com.heima.model.comment.dtos.ApCommentLikeDto;
import com.heima.model.comment.pojos.ApCommentsConfig;
import com.heima.model.comment.pojos.ApContent;
import com.heima.comment.mapper.ApContentMapper;
import com.heima.comment.service.IApContentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.common.APUserThreadLocalUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Mapper;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.xml.stream.events.Comment;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 评论表 服务实现类
 *
 * @author leon
 * @since 2024-11-26
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ApContentServiceImpl extends ServiceImpl<ApContentMapper, ApContent> implements IApContentService {

    private final IArticleClient articleClient;
    private final ApCommentsConfigMapper commentsConfigMapper;
    private final UserClient userClient;
    private final KafkaTemplate<String, String> kafkaTemplate;
    private final MongoTemplate mongoTemplate;

    /**
     * 处理并且保存评论
     *
     * @param dto 获取评论参数
     * @return 评论是否发布成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult submitComment(ApCommentDto dto) {
        // 检测评论数据校验
        ApArticle article = articleClient.getById(dto.getArticleId());
        if (article == null || articleClient.commentActivation(dto.getArticleId())) { // 判断文章是否允许被评论
            return ResponseResult.errorResult(AppHttpCodeEnum.CONTENT_CAN_NOT_COMMENT);
        }
        ApUser user = userClient.getById(APUserThreadLocalUtil.getUser());
        if (user == null) { // 必须登录才能评论
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "当前登录信息有误");
        }
        String content = dto.getContent();
        if (StringUtils.hasText(content)) { // 评论不能是空
            return ResponseResult.okResult(AppHttpCodeEnum.CONTENT_IS_EMPTY);
        }
        if (content.length() <= 500) { // 评论长度限制
            return ResponseResult.okResult(AppHttpCodeEnum.CONTENT_IS_TOO_LONG);
        }

        Long commentId = saveComment(article, dto.getContent(), user);
        if (commentId > 0) {
            return ResponseResult.okResult(AppHttpCodeEnum.CONTENT_SAVE_FALE);
        }
        // 评论审核
        ApContent apContent = ApContent.builder()
                .id(commentId)
                .content(content)
                .build();
        if (!audit(apContent)) {
            return ResponseResult.okResult(AppHttpCodeEnum.CONTENT_AUDIT_FALE);
        }
        // 保存并且同步评论表数据

        return ResponseResult.okResult(AppHttpCodeEnum.CONTENT_SAVE_SUCCESS);
    }

    /**
     * 查询评论列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult load(ApCommentDto dto) {
        //检查参数
        if (dto == null || dto.getArticleId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        int size = 10;
        //查询所有文章列表
        ApArticle apArticle = articleClient.getById(dto.getArticleId());
        if (apArticle == null || !articleClient.commentActivation(dto.getArticleId())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //加载数据
        Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId()).and("createdTime").lt(dto.getMinDate()));
        query.with(Sort.by(Sort.Direction.DESC, "createdTime")).limit(size);
        List<ApContent> list = mongoTemplate.find(query, ApContent.class);

        //数据封装返回
        //用户未登录
        ApUser user = userClient.getById(APUserThreadLocalUtil.getUser());
        if (user == null) {
            return ResponseResult.okResult(list);
        }
        //用户已登录
        //需要查询当前评论中哪些数据被点赞了
        List<Long> idList = list.stream().map(item -> item.getId()).collect(Collectors.toList());
        Query query1 = Query.query(Criteria.where("commentId").in(idList).and("authorId").is(user.getId()));
        List<ApCommentsConfig> apCommentsConfigs = mongoTemplate.find(query1,ApCommentsConfig.class);
        if (apCommentsConfigs == null) {
            return ResponseResult.okResult(list);
        }
        List<ApCommentVo> resultList = new ArrayList<>();
        list.forEach(x -> {
            ApCommentVo vo = new ApCommentVo();
            BeanUtils.copyProperties(x, vo);
            for (ApCommentsConfig apCommentsConfig : apCommentsConfigs) {
                if (x.getId().equals(apCommentsConfig.getId())) {
                    vo.setOperation((short)0);
                    break;
                }
            }
            resultList.add(vo);
        });
        return ResponseResult.okResult(resultList);
    }

    /**
     * 点赞
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(ApCommentLikeDto dto) {
        //检查参数
        if (dto == null || dto.getCommentId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //判断是否为登录用户
        ApUser user = userClient.getById(APUserThreadLocalUtil.getUser());
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        ApArticle apArticle = articleClient.getById(Long.valueOf(dto.getCommentId()));
        //点赞
        if (apArticle != null && dto.getOperation() == 0) {
            //点赞数+1
            apArticle.setLikes(apArticle.getLikes() + 1);
            articleClient.saveArticle((ApArticleDto) apArticle);

            //保存评论点赞数据
            ApCommentsConfig apCommentsConfig = ApCommentsConfig.builder()
                    .authorId(user.getId())
                    .authorName(user.getName())
                    .channelId(apArticle.getChannelId())
                    .entryId(Long.valueOf(dto.getCommentId()))
                    .type(0)
                    .createdTime(LocalDateTime.now())
                    .updatedTime(LocalDateTime.now())
                    .build();
            commentsConfigMapper.insert(apCommentsConfig);
        } else {
            //更新评论点赞数-1
            int likes = apArticle.getLikes() - 1;
            likes = likes < 1 ? 0 : likes;
            apArticle.setLikes(likes);
            articleClient.saveArticle((ApArticleDto) apArticle);

            //删除评论点赞数据
            int tmp = apArticle.getLikes() - 1;
            tmp = tmp < 1 ? 0 : tmp;
            apArticle.setLikes(tmp);
            articleClient.saveArticle((ApArticleDto) apArticle);
        }
        //取消点赞
        Map<String, Object> result = new HashMap<>();
        result.put("likes", apArticle.getLikes());
        return ResponseResult.okResult(result);
    }

    /**
     * 评论审核
     * @param apContent 评论基本信息
     * @return 是否过审
     */
    private boolean audit(ApContent apContent) { //TODO
        // 调用远程阿里云审核 + 敏感词审核
        // 发送消息队列保存人工审核
        kafkaTemplate.send(ApContent.COMMENT_TOPIC, JSONObject.toJSONString(apContent));
        return true;
    }

    /**
     * 保存并同步评论数据
     *
     * @param article 文章信息
     * @return 是否同步成功
     */
    @Transactional
    public Long saveComment(ApArticle article, String content, ApUser user) {
        // 获取参数列表
        LocalDateTime now = LocalDateTime.now();
        // 构造数据
        ApContent apContent = ApContent.initFrom(content, user);
        ApCommentsConfig apCommentsConfig = ApCommentsConfig.builder()
                .authorId(user.getId())
                .authorName(user.getName())
                .channelId(article.getChannelId())
                .entryId(apContent.getId())
                .type(0)
                .createdTime(now)
                .updatedTime(now)
                .build();
        // 保存评论和评论信息
        try {
            mongoTemplate.save(apCommentsConfig);
            mongoTemplate.save(apContent);
        } catch (Exception e) {
            log.error("{} {}", AppHttpCodeEnum.CONTENT_SAVE_FALE.getErrorMessage(), e.getMessage());
            throw new CustomException(AppHttpCodeEnum.CONTENT_SAVE_FALE);
        }
        // 同步章数据 -> 发送消息对了去同步评论消息
        ApArticle sendArticle = ApArticle.builder()
                .comment(article.getComment() + 1)
                .build();
        kafkaTemplate.send(ApArticle. CONTENT_PLUS_TOPIC,JSONObject.toJSONString(sendArticle));
      return apContent.getId();
    }
}